Linker Script

2024-06-21

最后编辑于:2024-09-15

    #asm

objdump -h View sections of object file objdump -t View symbol table

链接脚本的主要目的是将多个输入文件的各部分映射到输出文件中,并控制输出文件的布局

输入的目标文件中包含多个段 段有可加载的(loadable),可分配的,既不可装载也不可分配的段通常包含调试信息

可加载和可分配的输出段都有虚拟内存(VMA)加载内存地址(LMA)两个地址

SECTIONS段命令

语法:

section [address] [(type)] :
	[AT(lma)]
	[ALIGN(section_align) | ALIGN_WITH_INPUT]
	[SUBALIGN(subsection_align)]
	[constraint]
	{
		output-section-command
		output-section-command
		…
	} [>region] [AT>lma_region] [:phdr :phdr …] [=fillexp] [,]
SECTIONS
{
  . = 0x10000;
  .text : { *(.text) }
  . = 0x8000000;
  .data : { *(.data) }
  .bss : { *(.bss) }
}

.location counter 这里代码段从0x10000处加载,数据段从0x8000000开始

MEMORY内存命令

链接器默认允许分配所有可用的内存,通过MEMORY可以手动设置可用内存大小 语法:

MEMORY
{
	name [(attr)] : ORIGIN = orgin, LENGTH = len
}

可设置的属性

| R | Read-only section | | --- | ------------------- | | W | Read/write section | | X | Executable section | | A | Allocatable section | | I | Initialized section | | L | Same as I | | ! | Invert the sense | 例子:

MEMORY
{
	ROM (rx) : ORIGIN = 0, LENGTH = 256L
	RAM (!rx) : org = 0x40000000, l = 4M
}

Entry Point

有几种设置入口点的方法。 链接器将通过依次尝试以下每种方法来设置入口点,并在其中一种成功后停止:

  • "-e"输入命令行选项;
  • 链接描脚本中的ENTRY(symbol)命令;
  • 目标专用符号值(如果已定义); 对于许多目标来说是start符号
  • .text段的第一个字节的地址(如果存在);
  • 地址0。

Memory region alias

可以为MEMORY命令创建的内存区域创建别名,每个名称最多对应一个存储区域 语法:

REGION_ALIAS(alias, region)

假设一个程序,需要加载到不同类型的内存组合上

| Section | A | B | | ------- | :-: | :-----: | | .text | RAM | ROM | | .rodata | RAM | ROM | | .data | RAM | RAM/ROM | | .bss | RAM | RAM |

内存组合A linkcmds.memory

MEMORY
{
	RAM : ORIGIN = 0, LENGTH = 4M
}
REGION_ALIAS("REGION_TEXT", RAM);
REGION_ALIAS("REGION_RODATA", RAM);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);

内存组合B linkcmds.memory

MEMORY
{
	ROM : ORIGIN = 0, LENGTH = 3M;
	RAM : ORIGIN = 0x10000000, LENGTH = 1M
}
REGION_ALIAS("REGION_TEXT", ROM);
REGION_ALIAS("REGION_RODATA", ROM);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);

使用一个链接脚本

INCLUDE linkcmds.memory

SECTIONS
{
	.text :
	{
		*(.text)
	} > REGION_TEXT

	.rodata :
	{
		*(.rodata)
	} > REGION_RODATA
}

PHDRS

设置ELF程序头

PHDRS
{
  name type [ FILEHDR ] [ PHDRS ] [ AT ( address ) ]
        [ FLAGS ( flags ) ] ;
}

FILEHDR,PHDRS,AT是关键字